<style>
.crop-btn {
    position: relative;
    width: 148px;
    height: 148px;
    border: 1px dashed #c0ccda;
    border-radius: 6px;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    cursor: pointer;
}
.cropper-dialog .cropper-content {
    margin: auto;
}
.cropper-content .crop-image {
    position: relative;
    border: 1px dashed #c0ccda;
    border-radius: 6px;
}
.cropper-content .crop-entity {
    width: 100%;
    height: 100%;
}
.cropper-content .cropper-btns {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    margin-top: 20px;
    max-width: 300px;
}
.cropper-content .space-between {
    justify-content: space-between;
}
.cropper-content .preview {
    border: dashed 1px rgba(255, 255, 255, 0.25);
}
</style>

<template>
    <div class="crop-btn" @click="dialogVisible = true" :style="{ backgroundImage: 'url(' + value + ')' }">
        <el-dialog title="选择图片裁剪" class="cropper-dialog" :visible.sync="dialogVisible" width="500px" append-to-body destroy-on-close>
            <div class="cropper-content" :style="{ width: containerSize.width }">
                <!-- 圆形 -->
                <div class="crop-image" :style="{ height: containerSize.height }">
                    <cropper
                        v-if="loading"
                        class="crop-entity"
                        ref="cropper"
                        :src="image.src"
                        :stencil-props="stencilProps"
                        :debounce="'unlimited' === this.type"
                        :image-restriction="imageRestriction"
                        :stencil-size="psdSize"
                        :stencil-component="stencilComponent"
                    ></cropper>
                </div>
                <input type="file" ref="file" @change="loadImage($event)" accept="image/*" v-show="0" />

            </div>
            <div slot="footer"  >
                <el-button type="primary" @click="tailorImg"> 选择图片 </el-button>
                <el-button type="primary" @click="uploadImage" v-if="image.src">确认裁剪</el-button>
                <el-button type="primary" @click="reset" v-if="image.src">重置</el-button>
            </div>

        </el-dialog>
    </div>
</template>

<script>
Rap.define('', [], function () {
    return {
        name: 'ly-cropper',
        inheritAttrs: false,
        props: {
            // 图片路径
            value: {
                type: String,
                default: '',
            },
            // 裁剪模式
            // unlimited：不限制裁剪模式；circle：圆；lock：锁定纵横比；fixation：固定
            type: {
                type: String,
                default: 'unlimited',
            },
            // 矩形纵横比
            aspectRatio: {
                type: Number,
                default: 6 / 9,
            },
            // 剪切容器大小
            boxSize: {
                type: Object,
                default: function () {
                    return {
                        width: 300,
                        height: 300,
                    };
                },
            },
            // 裁剪框大小，仅在 固定模板尺寸(type: fixation)中生效
            stencilSize: {
                type: Object,
                default: function () {
                    return {
                        width: 280,
                        height: 280,
                    };
                },
            },
        },
        data: function () {
            return {
                dialogVisible: false,
                loading: false,
                image: {
                    src: null,
                    type: null,
                },
                result: {
                    coordinates: {
                        top: 0,
                        left: 0,
                    },
                    image: {},
                },
            };
        },
        computed: {
            containerSize: function () {
                return {
                    width: (this.boxSize.width || 300) + 'px',
                    height: (this.boxSize.height || 300) + 'px',
                }
            },
            stencilProps: function () {
                var stencil = undefined;
                if ('lock' === this.type) {
                    stencil = { aspectRatio: this.aspectRatio };
                } else if ('fixation' === this.type) {
                    stencil = {
                        handlers: {},
                        movable: false,
                        scalable: false,
                    };
                } else if ('circle' === this.type) {
                    stencil = {
                        previewClass: 'preview',
                    };
                }
                return stencil;
            },
            imageRestriction: function () {
                var restriction = undefined;
                if ('fixation' === this.type) {
                    restriction = 'stencil';
                }
                return restriction;
            },
            psdSize: function () {
                var size = undefined;
                if ('fixation' === this.type) {
                    size = this.stencilSize;
                }
                return size;
            },
            // stencil-component="circle-stencil"
            stencilComponent: function () {
                var component = undefined;
                if ('circle' === this.type) {
                    component = 'circle-stencil';
                }
                return component;
            },
        },
        destroyed: function () {
            Rap.removeCss('/static/ly/libs/vue-advanced-cropper/style.css');
        },
        mounted: function () {
            var me = this;
            Rap.loadCss('/static/ly/libs/vue-advanced-cropper/style.css');
            Rap.insertScript(['/static/ly/libs/vue-advanced-cropper/index.umd.js']).then(function (cropper) {
                // 可以使用全局注册的组件：cropper, circle-stencil, rectangle-stencil, simple-handler, simple-line。
                me.loading = true;
            });
        },
        methods: {
            tailorImg() {
                this.$refs.file.click();
            },
            reset() {
                this.image = {
                    src: null,
                    type: null,
                };
            },
            loadImage(event) {
                var files = event.target.files;
                if (files && files[0]) {
                    if (this.image.src) {
                        URL.revokeObjectURL(this.image.src);
                    }
                    var blob = URL.createObjectURL(files[0]);
                    var reader = new FileReader();
                    reader.onload = (e) => {
                        this.image = {
                            src: blob,
                            type: getMimeType(e.target.result, files[0].type),
                        };
                    };
                    reader.readAsArrayBuffer(files[0]);
                }
            },
            uploadImage() {
                var me = this;
                var result = this.$refs.cropper.getResult();
                var canvas = result.canvas;
                var image = result.image;

                if (canvas) {
                    const form = new FormData();
                    canvas.toBlob((blob) => {
                        form.append('file', blob, 'file.jpg');
                        var picUploadUrl = Ly.config().picUploadUrl;
                        var ajax = new XMLHttpRequest();
                        ajax.open('POST', picUploadUrl, true);
                        ajax.send(form);
                        ajax.onreadystatechange = function () {
                            if (ajax.readyState == 4) {
                                if ((ajax.status >= 200 && ajax.status < 300) || ajax.status == 304) {
                                    var obj = JSON.parse(ajax.responseText);
                                    var url = obj.url;
                                    if (url) {
                                        url = url.replace("?x-oss-process=video/snapshot,t_1000,m_fast", "");
                                        me.$emit('input', url);
                                        me.$emit('confirm', obj);
                                        me.dialogVisible = false;
                                    } else {
                                        var msg = obj.msg || '图片上传失败';
                                        App.$message({
                                            message: msg,
                                            type: 'warning'
                                        });
                                    }
                                }
                            }
                        };
                    }, 'image/jpg');
                }
            },
            reset() {
                this.image = {
                    src: null,
                    type: null,
                };
            },
        },
        destroyed() {
            if (this.image.src) {
                URL.revokeObjectURL(this.image.src);
            }
        },
    };
});
function getMimeType(file, fallback = null) {
    var byteArray = new Uint8Array(file).subarray(0, 4);
    var header = '';
    for (var i = 0; i < byteArray.length; i++) {
        header += byteArray[i].toString(16);
    }
    switch (header) {
        case '89504e47':
            return 'image/png';
        case '47494638':
            return 'image/gif';
        case 'ffd8ffe0':
        case 'ffd8ffe1':
        case 'ffd8ffe2':
        case 'ffd8ffe3':
        case 'ffd8ffe8':
            return 'image/jpeg';
        default:
            return fallback;
    }
}
</script>
